﻿//-----------------------------------------------------------------------
// <copyright file="OrderLine.cs" company="Craig Longford (deltawolf7@gmail.com)">
//     Copyright (c) Craig Longford. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace Delta.Mercury.Business.Commerce
{
    using System;
    using Delta.Data.DataExpress;
    using Delta.Mercury.Business.Exceptions;

    /// <summary>
    /// Order line class
    /// </summary>
    [Serializable]
    public class OrderLine : IdentifierBase, IDataServicable
    {
        #region Members
        /// <summary>
        /// Product name
        /// </summary>
        private string productName;

        /// <summary>
        /// Product SKU
        /// </summary>
        private string productSKU;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the OrderLine class
        /// </summary>
        public OrderLine()
            : this(Guid.Empty, string.Empty, string.Empty, 0.0M, 0, 0.0M)
        {
        }

        /// <summary>
        /// Initializes a new instance of the OrderLine class
        /// </summary>
        /// <param name="orderGuid">Order unique indetifier</param>
        /// <param name="productName">Product name</param>
        /// <param name="productSKU">Product sku</param>
        /// <param name="price">Product price</param>      
        /// <param name="qty">Product qty</param>
        /// <param name="tax">Product tax</param>
        public OrderLine(Guid orderGuid, string productName, string productSKU, decimal price, int qty, decimal tax)
            : base()
        {
            this.OrderGuid = orderGuid;
            this.productName = productName;
            this.productSKU = productSKU;
            this.Cost = 0.0M;
            this.ManufacturerPartNumber = string.Empty;
            this.Price = price;
            this.Qty = qty;
            this.SupplierPartNumber = string.Empty;
            this.ProductGuid = Guid.Empty;
            this.Tax = tax;
        }

        /// <summary>
        /// Initializes a new instance of the OrderLine class
        /// </summary>
        /// <param name="product">Product object</param>
        /// <param name="order">Order reference</param>
        /// <param name="qty">Qty ordered</param>
        public OrderLine(IProduct product, ref Order order, int qty)
            : base()
        {
            this.OrderGuid = order.Guid;
            this.productName = product.Name;
            this.productSKU = product.SKU;
            this.Cost = product.Cost;
            this.ManufacturerPartNumber = product.ManufacturerPartNumber;
            this.Price = product.Price;
            this.Qty = qty;
            this.SupplierPartNumber = product.SupplierPartNumber;
            this.ProductGuid = product.Guid;
            if (product.Taxable)
            {
                this.Tax = decimal.Parse(Setting.Load("MERCURY.VATRATE").Value);
            }
            else
            {
                this.Tax = 0.0M;
            }
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the order unique identifier
        /// </summary>
        public Guid OrderGuid { get; set; }

        /// <summary>
        /// Gets or sets the product name
        /// </summary>
        public string ProductName
        {
            get
            {
                return this.productName;
            }

            set
            {
                if (value.Length < 1)
                {
                    throw new InvalidLengthException("Product name must be a minimum of 1 characters.");
                }

                if (value.Length > 50)
                {
                    throw new InvalidLengthException("Product name must be a maximum of 50 characters.");
                }

                this.productName = value;
            }
        }

        /// <summary>
        /// Gets or sets the product sku
        /// </summary>
        public string SKU
        {
            get
            {
                return this.productSKU;
            }

            set
            {
                if (value.Length < 1)
                {
                    throw new InvalidLengthException("Product sku must be a minimum of 1 characters.");
                }

                if (value.Length > 20)
                {
                    throw new InvalidLengthException("Product sku must be a maximum of 20 characters.");
                }

                this.productSKU = value.ToUpper();
            }
        }

        /// <summary>
        /// Gets or sets the cost price
        /// </summary>
        public decimal Cost { get; set; }

        /// <summary>
        /// Gets or sets the sale price
        /// </summary>
        public decimal Price { get; set; }

        /// <summary>
        /// Gets or sets the manufacturer part number
        /// </summary>
        public string ManufacturerPartNumber { get; set; }

        /// <summary>
        /// Gets or sets the supplier part number
        /// </summary>
        public string SupplierPartNumber { get; set; }

        /// <summary>
        /// Gets or sets the qty ordered
        /// </summary>
        public int Qty { get; set; }

        /// <summary>
        /// Gets or sets the product guid
        /// </summary>
        public Guid ProductGuid { get; set; }

        /// <summary>
        /// Gets or sets the product tax
        /// </summary>
        public decimal Tax { get; set; }
        #endregion

        #region Get Product
        /// <summary>
        /// Get product
        /// </summary>
        /// <returns>Linked product</returns>
        public Product GetProduct()
        {
            return Product.Load(this.ProductGuid, false);
        }
        #endregion

        #region Save Methods
        /// <summary>
        /// Save order line
        /// </summary>
        public void Save()
        {
            DataAccess.NonQuery("SaveOrderLine", System.Data.CommandType.StoredProcedure, GetSaveParameters());
        }
        #endregion

        #region Fill Method
        /// <summary>
        /// Fill order line
        /// </summary>
        /// <param name="reader">Data reader</param>
        public void Fill(System.Data.IDataReader reader)
        {
            this.Cost = Helper.ToDecimal(reader["ProductCost"]);
            this.Guid = Helper.ToGuid(reader["Guid"]);
            this.ManufacturerPartNumber = Helper.ToString(reader["ProductMftPart"]);
            this.OrderGuid = Helper.ToGuid(reader["OrderGuid"]);
            this.Price = Helper.ToDecimal(reader["ProductPrice"]);
            this.ProductGuid = Helper.ToGuid(reader["ProductGuid"]);
            this.productName = Helper.ToString(reader["ProductName"]);
            this.productSKU = Helper.ToString(reader["ProductSKU"]);
            this.Qty = Helper.ToInt(reader["ProductQty"]);
            this.SupplierPartNumber = Helper.ToString(reader["ProductSupPart"]);
            this.Tax = Helper.ToDecimal(reader["ProductTax"]);
        }
        #endregion

        #region Get Save Parameters
        /// <summary>
        /// Get save parameters
        /// </summary>
        /// <returns>Parameter collection</returns>
        public Parameters GetSaveParameters()
        {
            Parameters parameters = new Parameters();
            parameters.Add(new Parameter("Guid", this.Guid));
            parameters.Add(new Parameter("OrderGuid", this.OrderGuid));
            parameters.Add(new Parameter("ProductSKU", this.SKU));
            parameters.Add(new Parameter("ProductName", this.ProductName));
            parameters.Add(new Parameter("ProductCost", this.Cost));
            parameters.Add(new Parameter("ProductPrice", this.Price));
            parameters.Add(new Parameter("ProductTax", this.Tax));
            parameters.Add(new Parameter("ProductQty", this.Qty));
            parameters.Add(new Parameter("ProductGuid", this.ProductGuid));
            parameters.Add(new Parameter("ProductMftPart", this.ManufacturerPartNumber));
            parameters.Add(new Parameter("ProductSupPart", this.SupplierPartNumber));
            return parameters;
        }
        #endregion
    }
}
